package info.hexin.mvc.methodtree;

import info.hexin.lang.Exceptions;
import info.hexin.lang.Strings;
import info.hexin.log.Log;
import info.hexin.log.Logs;
import info.hexin.mvc.annotation.Method;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 
 * @author ydhexin@gmail.com
 * 
 */
public class UrlNode {
    private static final Log log = Logs.get();
    // private MethodInfo methodInfo;
    private Map<String, UrlNode> children = new HashMap<String, UrlNode>();
    // 同一个url 有多个请求
    private Map<String, List<MethodInfo>> curMap = new HashMap<String, List<MethodInfo>>();

    public Map<String, UrlNode> getChildren() {
        return children;
    }

    public void setChildren(Map<String, UrlNode> children) {
        this.children = children;
    }

    /**
     * 对于保存url树时，如果碰到"{}"形式的话，保存成占位符"?"
     * 
     * @param methodInfo
     */
    public void addMethod(MethodInfo methodInfo) {
        String url = methodInfo.getUrl();
        String[] urls = url.split("/");
        UrlNode node = this;

        for (int i = 0; i < urls.length; i++) {
            String urlString = urls[i];
            if (urlString.contains("{")) {
                urlString = "?";
            } else if (urlString.equals("*")) {
                urlString = "*";
            }
            if (Strings.isBlank(urlString) && i == 0) {
                // 以/开头的url
                continue;
            }

            if (i == urls.length - 1) {
                List<MethodInfo> methodInfos = node.curMap.get(urlString);
                if (methodInfos == null) {
                    methodInfos = new ArrayList<MethodInfo>();
                }
                methodInfos.add(methodInfo);
                node.curMap.put(urlString, methodInfos);
                break;
            }

            if (node.children.containsKey(urlString)) {
                node = node.children.get(urlString);
            } else {
                UrlNode childrenNode = new UrlNode();
                node.children.put(urlString, childrenNode);
                node = childrenNode;
            }
        }
    }

    /**
     * 如果没有找到 返回null, 由于存在pathParam 所有用占位符。 查找，先用真实url找，如果找不到用占位符去找
     * 
     * @param url
     * @return
     */
    @SuppressWarnings("unused")
    public MethodInfo getUrl(String url, Method method) {
        //请求可以能为http://aa.com//tt
        url = url.replaceAll("//", "/");
        if (url.charAt(0) == '/') {
            url = url.substring(1);
        }

        if (url.contains(".")) {
            url = url.substring(0, url.indexOf('.'));
        }

        String[] urls = url.split("/");
        UrlNode node = this;

        if (node.children.size() == 0 && node.curMap.size() == 0) {
            throw Exceptions.make("r u configuration \"Path\" annotation or \"web.xml\" configuration packages");
        }

        int i = 0;
        while (i < urls.length) {
            String tempPath = urls[i];
            log.debug("获取iocbean tempPath >>>> " + tempPath);
            if (i++ == urls.length - 1) {
                // 获取优先级 所有匹配 > 通配 (?) > 泛配 (*)
                MethodInfo methodInfo = null;
                List<MethodInfo> methodInfos = node.curMap.get(tempPath);
                if (methodInfos != null && methodInfos.size() > 0) {
                    for (MethodInfo m : methodInfos) {
                        if (method.equal(m.getMethod())) {
                            methodInfo = m;
                            break;
                        }
                    }
                } else if (methodInfo == null) {
                    methodInfos = node.curMap.get("?");
                    if (methodInfos != null && methodInfos.size() > 0) {
                        for (MethodInfo m : methodInfos) {
                            if (method.equal(m.getMethod())) {
                                methodInfo = m;
                                break;
                            }
                        }
                    }
                } else if (methodInfo == null) {
                    methodInfos = node.curMap.get("*");
                    if (methodInfos != null && methodInfos.size() > 0) {
                        for (MethodInfo m : methodInfos) {
                            if (method.equal(m.getMethod())) {
                                methodInfo = m;
                                break;
                            }
                        }
                    }
                }
                return methodInfo;
            }

            // 获取优先级 所有匹配 > 通配 (?) > 泛配 (*)
            UrlNode tmpNode = node.children.get(tempPath);
            if (node == null) {
                tmpNode = node.children.get("?");
            } else if (tmpNode == null) {
                tmpNode = node.children.get("*");
            }
            node = tmpNode;
        }
        return null;
    }
}
